<!doctype html>

<html>

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

  <script src="../../webcomponentsjs/webcomponents-lite.js"></script>
  <script src="../../web-component-tester/browser.js"></script>
  <script src="../../iron-test-helpers/mock-interactions.js"></script>
  <link rel="import" href="../../test-fixture/test-fixture.html">

  <link rel="import" href="helpers.html">
  <link rel="import" href="../vaadin-grid.html">
</head>

<body>

  <test-fixture id="small">
    <template>
      <vaadin-grid style="width: 200px; height: 200px;" size="100">
        <vaadin-grid-column>
          <template class="header">foo</template>
          <template>[[index]]</template>
        </vaadin-grid-column>
      </vaadin-grid>
    </template>
  </test-fixture>

  <test-fixture id="large">
    <template>
      <vaadin-grid style="width: 200px; height: 500px;" size="500000000">
        <vaadin-grid-column>
          <template class="header">foo</template>
          <template>[[index]]</template>
        </vaadin-grid-column>
      </vaadin-grid>
    </template>
  </test-fixture>

  <script>
    describe('Scroll to index', () => {

      ['small', 'large'].forEach(scale => {

        describe('Scroll: ' + scale, () => {
          let grid;

          beforeEach(done => {
            grid = fixture(scale);
            grid.dataProvider = infiniteDataProvider;
            flushGrid(grid);
            animationFrameFlush(done);
          });

          it('should scroll to scaled index', () => {
            [0, 1, 2, 3, 5, 8, 13, 21, 34, 55, 77, 88, 100].forEach(percentage => {
              const index = Math.ceil((grid.size - 1) * percentage / 100);
              grid.scrollToIndex(grid._firefox ? 1 : 0); // FF58 workaround
              grid.scrollToIndex(index);

              if (percentage === 100) {
                expect(grid._vidxOffset + grid.lastVisibleIndex).to.equal(index);

                const table = grid.$.table;
                expect(table.scrollTop).to.equal(table.scrollHeight - table.offsetHeight);
              } else {
                expect(grid._vidxOffset + grid._firstVisibleIndex).to.equal(index);
              }

            });
          });

          it('should scroll to last index', () => {
            grid.scrollToIndex(grid.size * 2);
            expect(grid._vidxOffset + grid.lastVisibleIndex).to.equal(grid.size - 1);
          });

          it('should scroll to first index', () => {
            grid.scrollToIndex(-100);
            expect(grid._vidxOffset + grid._firstVisibleIndex).to.equal(0);
          });

          it('should set scroll position half-way', () => {
            grid.scrollToIndex(grid.size / 2);
            flushGrid(grid);
            expect(grid.$.table.scrollTop).to.be.closeTo(
              (grid.$.table.scrollHeight - grid.$.table.offsetHeight) / 2, grid.$.table.scrollHeight / 20
            );
          });

          it('should retain virtual scroll position on size change', () => {
            const index = grid.size / 2;
            grid.scrollToIndex(index);
            flushGrid(grid);
            grid.scrollTop += 1; // Scroll a little to validate the test
            let row = Array.from(grid.$.items.children).filter(r => r.index === index)[0];
            const rowTop = row.getBoundingClientRect().top;

            grid.size -= ~~(grid.size / 4);
            row = Array.from(grid.$.items.children).filter(r => r.index === index)[0];
            expect(row.getBoundingClientRect().top).to.be.closeTo(rowTop, 0.5);
          });

        });

      });

      describe('other', () => {
        let grid, scroller;

        beforeEach(done => {
          grid = fixture('large');
          grid.scrollToIndex(10);
          grid.dataProvider = infiniteDataProvider;
          flushGrid(grid);
          animationFrameFlush(done);
        });

        it('should schedule scroll to index', () => {
          expect(grid._firstVisibleIndex).to.equal(10);
        });

        it('should have correct indexes after scrolling', done => {
          const listener = () => {
            flushGrid(grid);
            // Check that the rows are in order
            const rows = grid.$.items.querySelectorAll('[part~="row"]');
            for (var i = 1; i < rows.length; i++) {
              expect(rows[i].index).to.equal(rows[i - 1].index + 1);
            }
            done();
          };

          grid.scrollToIndex(100);
          listenOnce(grid.$.table, 'scroll', listener);
          grid.$.table.scrollTop -= 1;
        });

        it('should scroll close to end', () => {
          const viewPortItemCount = Math.round(grid._viewportHeight / grid._physicalAverage - 1); // - header;
          const targetIndex = grid.size - viewPortItemCount - 2;
          grid.scrollToIndex(targetIndex);

          const rect = grid.$.header.getBoundingClientRect();
          grid.$.outerscroller.hidden = true;
          const cell = (Polymer.Settings.useShadow ? grid.shadowRoot : document).elementFromPoint(rect.left + 1, rect.bottom + 2);
          expect(cell.parentElement.index).to.equal(targetIndex);
        });

      });

    });
  </script>

</body>

</html>
